/*============================================================================*/
/*  Copyright (C) 2009-2013,  INFRASTRUCTURE SOFTWARE CO.,LTD.
 *  
 *  All rights reserved. This software is  property. Duplication 
 *  or disclosure without  written authorization is prohibited.
 *  
 *  
 *  @file       CanTp_Cbk.c
 *  @brief      Call-back function implementation
 *  
 *
 *  @author     stanley
 *  @date       2013-4-7
 */
/*============================================================================*/


/*=======[R E V I S I O N   H I S T O R Y]====================================*/
/*  <VERSION>    <DATE>    <AUTHOR>    <REVISION LOG>
 *  V1.0.0       2013-4-7   stanley    create
 *  V1.0.1       2019-12-5 tao.yu     QAC change
 *  V1.0.2       2020-1-7  tao.yu     Commercial project problem modification
 * 
 *  
 */
/*============================================================================*/

/*=======[V E R S I O N  I N F O R M A T I O N]===============================*/
#define CANTP_CBK_C_AR_MAJOR_VERSION  4
#define CANTP_CBK_C_AR_MINOR_VERSION  2
#define CANTP_CBK_C_AR_PATCH_VERSION  2
#define CANTP_CBK_C_SW_MAJOR_VERSION  1
#define CANTP_CBK_C_SW_MINOR_VERSION  0
#define CANTP_CBK_C_SW_PATCH_VERSION  2

/*required CANIF version*/
#define CANTP_CBK_C_CANIF_AR_MAJOR_VERSION  4
#define CANTP_CBK_C_CANIF_AR_MINOR_VERSION  2

/*required PDUR version*/
#define CANTP_CBK_C_PDUR_AR_MAJOR_VERSION  4
#define CANTP_CBK_C_PDUR_AR_MINOR_VERSION  2

/*required DEM version*/
#define CANTP_CBK_C_DEM_AR_MAJOR_VERSION  4
#define CANTP_CBK_C_DEM_AR_MINOR_VERSION  2

/*required DET version*/
#define CANTP_CBK_C_DET_AR_MAJOR_VERSION  4
#define CANTP_CBK_C_DET_AR_MINOR_VERSION  2

/*=======[I N C L U D E S]====================================================*/
#include "CanTp.h"
#include "CanTp_Cbk.h"
#include "CanTp_Internal.h"
#include "PduR_CanTp.h"
/*=======[V E R S I O N  C H E C K]===========================================*/
/*check version information with CanTp.h*/
#if (CANTP_CBK_C_AR_MAJOR_VERSION != CANTP_H_AR_MAJOR_VERSION)
  #error "CanTp_Cbk.c : Mismatch in Specification Major Version with CanTp.h"
#endif
#if (CANTP_CBK_C_AR_MINOR_VERSION != CANTP_H_AR_MINOR_VERSION)
  #error "CanTp_Cbk.c : Mismatch in Specification Minor Version with CanTp.h"
#endif
#if (CANTP_CBK_C_AR_PATCH_VERSION != CANTP_H_AR_PATCH_VERSION)
  #error "CanTp_Cbk.c : Mismatch in Specification Patch Version with CanTp.h"
#endif
#if (CANTP_CBK_C_SW_MAJOR_VERSION != CANTP_H_SW_MAJOR_VERSION)
  #error "CanTp_Cbk.c : Mismatch in Software Implementation Major Version with CanTp.h"
#endif
#if (CANTP_CBK_C_SW_MINOR_VERSION != CANTP_H_SW_MINOR_VERSION)
  #error "CanTp_Cbk.c : Mismatch in Software Implementation Minor Version with CanTp.h"
#endif

/*check version information with CanTp_Cbk.h*/
#if (CANTP_CBK_C_AR_MAJOR_VERSION != CANTP_CBK_H_AR_MAJOR_VERSION)
  #error "CanTp_Cbk.c : Mismatch in Specification Major Version with CanTp_Cbk.h"
#endif
#if (CANTP_CBK_C_AR_MINOR_VERSION != CANTP_CBK_H_AR_MINOR_VERSION)
  #error "CanTp_Cbk.c : Mismatch in Specification Minor Version with CanTp_Cbk.h"
#endif
#if (CANTP_CBK_C_AR_PATCH_VERSION != CANTP_CBK_H_AR_PATCH_VERSION)
  #error "CanTp_Cbk.c : Mismatch in Specification Patch Version with CanTp_Cbk.h"
#endif
#if (CANTP_CBK_C_SW_MAJOR_VERSION != CANTP_CBK_H_SW_MAJOR_VERSION)
  #error "CanTp_Cbk.c : Mismatch in Software Implementation Major Version with CanTp_Cbk.h"
#endif
#if (CANTP_CBK_C_SW_MINOR_VERSION != CANTP_CBK_H_SW_MINOR_VERSION)
  #error "CanTp_Cbk.c : Mismatch in Software Implementation Minor Version with CanTp_Cbk.h"
#endif

/*check version information with CanTp_Internal.h*/
#if (CANTP_CBK_C_AR_MAJOR_VERSION != CANTP_INTERNAL_H_AR_MAJOR_VERSION)
  #error "CanTp_Cbk.c : Mismatch in Specification Major Version with CanTp_Internal.h"
#endif
#if (CANTP_CBK_C_AR_MINOR_VERSION != CANTP_INTERNAL_H_AR_MINOR_VERSION)
  #error "CanTp_Cbk.c : Mismatch in Specification Minor Version with CanTp_Internal.h"
#endif
#if (CANTP_CBK_C_AR_PATCH_VERSION != CANTP_INTERNAL_H_AR_PATCH_VERSION)
  #error "CanTp_Cbk.c : Mismatch in Specification Patch Version with CanTp_Internal.h"
#endif
#if (CANTP_CBK_C_SW_MAJOR_VERSION != CANTP_INTERNAL_H_SW_MAJOR_VERSION)
  #error "CanTp_Cbk.c : Mismatch in Software Implementation Major Version with CanTp_Internal.h"
#endif
#if (CANTP_CBK_C_SW_MINOR_VERSION != CANTP_INTERNAL_H_SW_MINOR_VERSION)
  #error "CanTp_Cbk.c : Mismatch in Software Implementation Minor Version with CanTp_Internal.h"
#endif

/*check version information with CanTp_Types.h*/
#if (CANTP_CBK_C_AR_MAJOR_VERSION != CANTP_TYPES_H_AR_MAJOR_VERSION)
  #error "CanTp_Cbk.c : Mismatch in Specification Major Version with CanTp_Types.h"
#endif
#if (CANTP_CBK_C_AR_MINOR_VERSION != CANTP_TYPES_H_AR_MINOR_VERSION)
  #error "CanTp_Cbk.c : Mismatch in Specification Minor Version with CanTp_Types.h"
#endif
#if (CANTP_CBK_C_AR_PATCH_VERSION != CANTP_TYPES_H_AR_PATCH_VERSION)
  #error "CanTp_Cbk.c : Mismatch in Specification Patch Version with CanTp_Types.h"
#endif
#if (CANTP_CBK_C_SW_MAJOR_VERSION != CANTP_TYPES_H_SW_MAJOR_VERSION)
  #error "CanTp_Cbk.c : Mismatch in Software Implementation Major Version with CanTp_Types.h"
#endif
#if (CANTP_CBK_C_SW_MINOR_VERSION != CANTP_TYPES_H_SW_MINOR_VERSION)
  #error "CanTp_Cbk.c : Mismatch in Software Implementation Minor Version with CanTp_Types.h"
#endif

/*check version information with CanTp_Cfg.h*/
#if (CANTP_CBK_C_AR_MAJOR_VERSION != CANTP_CFG_H_AR_MAJOR_VERSION)
  #error "CanTp_Cbk.c : Mismatch in Specification Major Version with CanTp_Cfg.h"
#endif
#if (CANTP_CBK_C_AR_MINOR_VERSION != CANTP_CFG_H_AR_MINOR_VERSION)
  #error "CanTp_Cbk.c : Mismatch in Specification Minor Version with CanTp_Cfg.h"
#endif
#if (CANTP_CBK_C_AR_PATCH_VERSION != CANTP_CFG_H_AR_PATCH_VERSION)
  #error "CanTp_Cbk.c : Mismatch in Specification Patch Version with CanTp_Cfg.h"
#endif
#if (CANTP_CBK_C_SW_MAJOR_VERSION != CANTP_CFG_H_SW_MAJOR_VERSION)
  #error "CanTp_Cbk.c : Mismatch in Software Implementation Major Version with CanTp_Cfg.h"
#endif
#if (CANTP_CBK_C_SW_MINOR_VERSION != CANTP_CFG_H_SW_MINOR_VERSION)
  #error "CanTp_Cbk.c : Mismatch in Software Implementation Minor Version with CanTp_Cfg.h"
#endif

/*check version information with DEM*/
#if (CANTP_CBK_C_DEM_AR_MAJOR_VERSION != DEM_H_AR_MAJOR_VERSION)
  #error "CanTp_Cbk.c : Mismatch in Specification Major Version with Dem.h"
#endif
#if (CANTP_CBK_C_DEM_AR_MINOR_VERSION != DEM_H_AR_MINOR_VERSION)
  #error "CanTp_Cbk.c : Mismatch in Specification Minor Version with Dem.h"
#endif

#if (CANTP_DEV_ERROR_DETECT == STD_ON)
/*Check version information with DET*/
#if (CANTP_CBK_C_DET_AR_MAJOR_VERSION != DET_H_AR_MAJOR_VERSION)
  #error "CanTp_Cbk.c : Mismatch in Specification Major Version with Det.h"
#endif
#if (CANTP_CBK_C_DET_AR_MINOR_VERSION != DET_H_AR_MINOR_VERSION)
  #error "CanTp_Cbk.c : Mismatch in Specification Minor Version with Det.h"
#endif
#endif

/*Check version information with PDUR*/
#if (CANTP_CBK_C_PDUR_AR_MAJOR_VERSION != PDUR_CANTP_H_AR_MAJOR_VERSION)
  #error "CanTp_Cbk.c : Mismatch in Specification Major Version with PduR_CanTp.h"
#endif
#if (CANTP_CBK_C_PDUR_AR_MINOR_VERSION != PDUR_CANTP_H_AR_MINOR_VERSION)
  #error "CanTp_Cbk.c : Mismatch in Specification Minor Version with PduR_CanTp.h"
#endif

/*Check version information with CANIF*/
#if (CANTP_CBK_C_CANIF_AR_MAJOR_VERSION != CANIF_H_AR_MAJOR_VERSION)
  #error "CanTp_Cbk.c : Mismatch in Specification Major Version with CanIf.h"
#endif
#if (CANTP_CBK_C_CANIF_AR_MINOR_VERSION != CANIF_H_AR_MINOR_VERSION)
  #error "CanTp_Cbk.c : Mismatch in Specification Minor Version with CanIf.h"
#endif
/*=======[M A C R O S]========================================================*/

/*=======[T Y P E   D E F I N I T I O N S]====================================*/

/*=======[E X T E R N A L   D A T A]==========================================*/

/*=======[E X T E R N A L   F U N C T I O N   D E C L A R A T I O N S]========*/

/*=======[I N T E R N A L   D A T A]==========================================*/

/*=======[I N T E R N A L   F U N C T I O N   D E C L A R A T I O N S]========*/
#define CANTP_START_SEC_CODE
#include "Cantp_MemMap.h"
/*************************************************************************/
/*
 * Brief               This function is called by the CanTp_RxIndication after a successful
 *                     reception of a RX CAN L-PDU, put the PDU into pool.
 * ServiceId
 * Sync/Async          Synchronous
 * Reentrancy          Reentrant
 * Param-Name[in]      CanTpRxPduId the received N-PDU ID
 *                     CanTpRxPduPtr indicator of structure with received
 *                                   L-SDU(payload) and data length
 * Param-Name[out]     N/A
 * Param-Name[in/out]  N/A
 * Return              N/A
 * PreCondition        CanTp initialized
 * CallByAPI           CanTp_RxIndication
 */
/*************************************************************************/
static FUNC(void, CANTP_CODE)
CanTp_FillRxPdu(
    PduIdType CanTpRxPduId,
    P2CONST(PduInfoType, AUTOMATIC, CANTP_APPL_CONST) CanTpRxPduPtr);

/*************************************************************************/
/*
 * Brief               Handle Confirm event occurred to the specific channel.
 * ServiceId           N/A
 * Sync/Async          Synchronous
 * Reentrancy          Non Reentrant
 * Param-Name[in]      ChannelIdx index of channel
 * Param-Name[out]     N/A
 * Param-Name[in/out]  N/A
 * Return              N/A.
 * PreCondition        Module initialized.
 * CallByAPI           CanTp_MainFuncation
 */
/*************************************************************************/
static FUNC(void, CANTP_CODE)
CanTp_DispatchCfmEvent(uint8 ChannelIdx);


/*************************************************************************/
/*
 * Brief               Store the received RXNPDU when indicated.
 * ServiceId           N/A
 * Sync/Async          Synchronous
 * Reentrancy          Non Reentrant
 * Param-Name[in]      CanTpRxPduId ID of received NPDU
 *                     CanTpRxPduPtr pointer to data of received NPDU
 *                     RxNSduCfgPtr pointer to configuration structure of
 *                     this SDU matched with this received NPDU
 *                     FrameType frame type
 * Param-Name[out]     N/A
 * Param-Name[in/out]  N/A
 * Return              E_OK the received NPDU is expected
 *                     E_NOT_OK not expected NPDU
 * PreCondition        Module initialized, a NPDU received.
 * CallByAPI           CanTp_MainFunction
 */
/*************************************************************************/
static FUNC(Std_ReturnType, CANTP_CODE)
CanTp_StoreRxNPduEvt(
    PduIdType CanTpRxPduId,
    P2CONST(PduInfoType, AUTOMATIC, CANTP_APPL_CONST) CanTpRxPduPtr,
    P2CONST(CanTp_RxNSduType, AUTOMATIC, CANTP_CONST) RxNSduCfgPtr,
    CanTp_FramePCIType FrameType,
	uint8 channelIdx,
	P2VAR(boolean, AUTOMATIC, CANTP_CONST) FcFlag
    );


static FUNC(PduIdType, CANTP_CODE)
        CanTp_GetRxIPduId(PduIdType RcvdNPduId,uint8 channelIdx);


static FUNC(Std_ReturnType, CANTP_CODE)
CanTp_StoreRxNPduInfo(
	PduIdType CanTpRxPduId,
    P2CONST(PduInfoType, AUTOMATIC, CANTP_APPL_CONST) CanTpRxPduPtr,
    P2CONST(CanTp_RxNSduType, AUTOMATIC, CANTP_CONST) RxNSduCfgPtr,
	CanTp_FramePCIType FrameType,
	uint8 channelIdx
    );

	
#define CANTP_STOP_SEC_CODE
#include "Cantp_MemMap.h"

/*=======[F U N C T I O N   I M P L E M E N T A T I O N S]====================*/
#define CANTP_START_SEC_CODE
#include "Cantp_MemMap.h"


/*************************************************************************/
/*
 * Brief               This function is called by the CAN Interface after a successful
 *                     reception of a RX CAN L-PDU.
 * ServiceId           0x04
 * Sync/Async          Synchronous
 * Reentrancy          Reentrant
 * Param-Name[in]      CanTpRxPduId the received N-PDU ID
 *                     CanTpRxPduPtr indicator of structure with received
 *                                   L-SDU(payload) and data length
 * Param-Name[out]     N/A
 * Param-Name[in/out]  N/A
 * Return              N/A
 * PreCondition        CanTp initialized
 * CallByAPI           CAN Interface Receiving handling
 */
/*************************************************************************/
FUNC(void, CANTP_APPL_CODE)
CanTp_RxIndication(
    PduIdType RxPduId,
    P2CONST(PduInfoType, AUTOMATIC, CANTP_APPL_CONST) PduInfoPtr
    )
{
    /*check module state, handle the reception indication only when module started*/
    if (CANTP_ON == CanTp_ModuleState)
    {
        #if (CANTP_DEV_ERROR_DETECT == STD_ON)
        if ((NULL_PTR == PduInfoPtr)
            || (NULL_PTR == PduInfoPtr->SduDataPtr))
        {
            /*INVALID pointer parameter*/
        	Det_ReportRuntimeError(CANTP_MODULE_ID, CANTP_INSTANCE_ID, CANTP_SERVICEID_RXINDICATION, CANTP_E_PARAM_POINTER);
        }
        else
        { /*pointer not null*/
        #endif
			/*fill the received NPDU into channel*/
			CanTp_FillRxPdu(RxPduId, PduInfoPtr);
        #if (CANTP_DEV_ERROR_DETECT == STD_ON)
        } /*END OF pointer not null*/
        #endif

    } /*END OF CANTP_ON == CanTp_RuntimeControl.ModuleState*/
    #if (CANTP_DEV_ERROR_DETECT == STD_ON)
    else
    {
        /*CanTp module not started*/
        Det_ReportError(CANTP_MODULE_ID, CANTP_INSTANCE_ID, CANTP_SERVICEID_RXINDICATION, CANTP_E_UNINIT);
    }
    #endif
}

/*************************************************************************/
/*
 * Brief               All transmitted CAN frames belonging to the CAN Transport
 *                     Layer will be confirmed by this function.
 * ServiceId           0x05
 * Sync/Async          Synchronous
 * Reentrancy          Reentrant
 * Param-Name[in]      CanTpTxPduId ID of CAN L-PDU that has been transmitted
 * Param-Name[out]     N/A
 * Param-Name[in/out]  N/A
 * Return              N/A
 * PreCondition        CanTp initialized
 * CallByAPI           CAN Interface transmitting confirmation
 */
/*************************************************************************/
FUNC(void, CANTP_APPL_CODE)
CanTp_TxConfirmation(PduIdType TxPduId)
{
    P2CONST(CanTp_RxNSduType, AUTOMATIC, CANTP_CONST) rxNSduCfgPtr;
    P2CONST(CanTp_TxNSduType, AUTOMATIC, CANTP_CONST) txNSduCfgPtr;
    P2VAR(CanTp_ConnectionChannelType, AUTOMATIC, CANTP_VAR_POWER_ON_INIT) channelPtr;
    volatile boolean eventConsumed = FALSE;
    uint8 chnIdx;

    /*check module state, handle the reception indication only when module started*/
    if (CANTP_ON == CanTp_ModuleState)
    {
        /*first check if it is a transmitted data NPDU*/
        txNSduCfgPtr = CanTp_GetTxSduCfgByTxNPdu(TxPduId, &chnIdx);

        if (NULL_PTR != txNSduCfgPtr)
        {
            /*A transmitted data PDU confirmed*/
            /*Store the confirmation event only when the channel related with this TX SDU
             * is transmitting this SDU and it is waiting for the confirmation*/
            channelPtr = &CanTp_Channels[chnIdx];

            if (((CANTP_TX_SF_V4SF_CFM == channelPtr->TxConnection.Substate)
                    || (CANTP_TX_LARGE_V4DATA_CFM == channelPtr->TxConnection.Substate))
                && (txNSduCfgPtr->TxNSduId == channelPtr->TxConnection.NSduId))
            {
                channelPtr->TxConnection.EventFlags |= CANTP_CHANNEL_EVENT_TX_CONFIRMED;
                eventConsumed = TRUE;
            }
        } /*END OF handling data frame confirmation*/
#if (CANTP_DEV_ERROR_DETECT == STD_ON)
		else
		{
			/*invalid confirmation*/
			Det_ReportError(CANTP_MODULE_ID, CANTP_INSTANCE_ID, CANTP_SERVICEID_TXCONFIRMATION, CANTP_E_INVALID_TX_ID);
		}
#endif

        if (FALSE == eventConsumed)
        {
            /*then check if it is a transmitted FC NPDU*/
            rxNSduCfgPtr = CanTp_GetRxSduCfgByTxFCNPdu(TxPduId, &chnIdx);

            if (NULL_PTR != rxNSduCfgPtr)
            {
            	channelPtr = &CanTp_Channels[chnIdx];
                /*A transmitted FC PDU confirmed*/
                /*Store the confirmation event only when the channel related with this RX SDU
                 * is receiving this SDU and it is waiting for the FC confirmation*/
                if (((CANTP_RX_LARGE_V4FCCTS_CFM == channelPtr->RxConnection.Substate)
                        || (CANTP_RX_LARGE_V4FCWT_CFM == channelPtr->RxConnection.Substate))
                    && (rxNSduCfgPtr->RxNSduId == channelPtr->RxConnection.NSduId))
                {
                    channelPtr->RxConnection.EventFlags |= CANTP_CHANNEL_EVENT_TXFC_CONFIRMED;
                    eventConsumed = TRUE;
                }
            }
#if (CANTP_DEV_ERROR_DETECT == STD_ON)
			else
			{
				/*invalid confirmation*/
				Det_ReportError(CANTP_MODULE_ID, CANTP_INSTANCE_ID, CANTP_SERVICEID_TXCONFIRMATION, CANTP_E_INVALID_TX_ID);
			}
#endif
        } /*END OF FC confirmation*/

        if (TRUE == eventConsumed)
	    {
			/*handle confirmation events*/
			CanTp_DispatchCfmEvent(chnIdx);
	    }
#if 0   /*by tao.yu, the CanTp module shall send a Flow Control N-PDU with overflow status (FC(OVFLW)),When confirm not to DET*/
#if (CANTP_DEV_ERROR_DETECT == STD_ON)
		else
		{
			/*invalid confirmation*/
			Det_ReportError(CANTP_MODULE_ID, CANTP_INSTANCE_ID, CANTP_SERVICEID_TXCONFIRMATION, CANTP_E_INVALID_TX_ID);
		}
#endif
#endif
    } /*END OF CANTP_ON == CanTp_RuntimeControl.ModuleState*/
    #if (CANTP_DEV_ERROR_DETECT == STD_ON)
    else
    {
        /*CanTp module not started*/
        Det_ReportError(CANTP_MODULE_ID, CANTP_INSTANCE_ID, CANTP_SERVICEID_TXCONFIRMATION, CANTP_E_UNINIT);
    }
    #endif
}

static FUNC(PduIdType, CANTP_CODE)
        CanTp_GetRxIPduId(PduIdType RcvdNPduId,uint8 channelIdx)
{
    PduIdType RxIPduId = 0xFF;
    uint8 iloop;
    for (iloop = 0; ((iloop < CanTp_CfgData.CanTpChannel[channelIdx].RxNSduNum)
            && (RxIPduId == 0xFFu)); iloop++)
    {
        if (CanTp_CfgData.CanTpChannel[channelIdx].RxNSdus[iloop].RxNPduId == RcvdNPduId)
        {
            RxIPduId = CanTp_CfgData.CanTpChannel[channelIdx].RxNSdus[iloop].RxIPduId;
        }
    }
    return RxIPduId;
}

/*========[Internal STATIC Function Implementation]==================================*/
static FUNC(Std_ReturnType, CANTP_CODE)
CanTp_StoreRxNPduInfo(
	PduIdType CanTpRxPduId,
    P2CONST(PduInfoType, AUTOMATIC, CANTP_APPL_CONST) CanTpRxPduPtr,
    P2CONST(CanTp_RxNSduType, AUTOMATIC, CANTP_CONST) RxNSduCfgPtr,
	CanTp_FramePCIType FrameType,
	uint8 channelIdx
    )
{
	Std_ReturnType result = E_OK;
    P2VAR(CanTp_ConnectionChannelType, AUTOMATIC, CANTP_VAR_POWER_ON_INIT) channelPtr;
    PduIdType RxIPduId;

    channelPtr = &CanTp_Channels[channelIdx];

    /*Before Store Rxinfo shall clear the older Rx event*/
	if ((channelPtr->RxConnection.EventFlags & CANTP_CHANNEL_EVENT_SF_RECEIVED) != 0u)
	{
	    RxIPduId = CanTp_GetRxIPduId(channelPtr->RxConnection.RcvdNPduId,channelIdx);
		PduR_CanTpRxIndication(RxIPduId, E_NOT_OK);
        channelPtr->RxConnection.EventFlags =
        		channelPtr->RxConnection.EventFlags & ((uint16)~CANTP_CHANNEL_EVENT_SF_RECEIVED);
	}
	if ((channelPtr->RxConnection.EventFlags & CANTP_CHANNEL_EVENT_FF_RECEIVED) != 0u)
	{
        RxIPduId = CanTp_GetRxIPduId(channelPtr->RxConnection.RcvdNPduId,channelIdx);
		PduR_CanTpRxIndication(RxIPduId, E_NOT_OK);
		channelPtr->RxConnection.EventFlags =
				channelPtr->RxConnection.EventFlags & ((uint16)~CANTP_CHANNEL_EVENT_FF_RECEIVED);
	}
	if ((channelPtr->RxConnection.EventFlags & CANTP_CHANNEL_EVENT_CF_RECEIVED) != 0u)
	{
        RxIPduId = CanTp_GetRxIPduId(channelPtr->RxConnection.RcvdNPduId,channelIdx);
		PduR_CanTpRxIndication(RxIPduId, E_NOT_OK);
		channelPtr->RxConnection.EventFlags =
				channelPtr->RxConnection.EventFlags & ((uint16)~CANTP_CHANNEL_EVENT_CF_RECEIVED);
	}
	if ((channelPtr->RxConnection.EventFlags & CANTP_CHANNEL_EVENT_FC_RECEIVED) != 0u)
	{
        RxIPduId = CanTp_GetRxIPduId(channelPtr->RxConnection.RcvdNPduId,channelIdx);
		PduR_CanTpRxIndication(RxIPduId, E_NOT_OK);
		channelPtr->RxConnection.EventFlags =
				channelPtr->RxConnection.EventFlags & ((uint16)~CANTP_CHANNEL_EVENT_FC_RECEIVED);
	}

    CanTp_MemoryCopy(	CanTpRxPduPtr->SduDataPtr,
    					channelPtr->RxConnection.LocalBuf,
						CanTpRxPduPtr->SduLength);
    channelPtr->RxConnection.RcvdNPduId = CanTpRxPduId;
    channelPtr->RxConnection.RcvdNSduId = RxNSduCfgPtr->RxNSduId;
    channelPtr->RxConnection.MetaDataLength = RxNSduCfgPtr->MetaDataLength;
    channelPtr->RxConnection.DataLen = CanTpRxPduPtr->SduLength;

    if (FrameType == CANTP_FTYPE_CF)
    {
    	channelPtr->RxConnection.EventFlags |= CANTP_CHANNEL_EVENT_CF_RECEIVED;
		#if (CANTP_GENERIC_CONNECTION_SUPPORT == STD_ON)
		if (CanTp_Channels[channelIdx].RxConnection.MetaDataLength > 0u)
		{
			/*SWS_CanTp_00333,check the addressing information contained in the MetaData of the N-PDU (at the end
			 *  of the data referenced by PduInfoPtr) against the stored values from the FF.*/
			result = CanTp_CheckRxCFMetaData(channelIdx, RxNSduCfgPtr, CanTpRxPduPtr);
		}
		#endif
    }
    else if (FrameType == CANTP_FTYPE_FF)
    {
		/*transit the sub-state in order to ignore the following events related with the last reception*/
		channelPtr->RxConnection.Substate = CANTP_SUBSTATE_NONE;
		channelPtr->RxConnection.EventFlags |= CANTP_CHANNEL_EVENT_FF_RECEIVED;
		#if (CANTP_GENERIC_CONNECTION_SUPPORT == STD_ON)
		if (channelPtr->RxConnection.MetaDataLength > 0u)
		{
			result = CanTp_SaveRxMetaDataInfo(channelIdx, RxNSduCfgPtr, CanTpRxPduPtr);
		}
		#endif
    }
    else if (FrameType == CANTP_FTYPE_SF)
    {
		/*transit the sub-state in order to ignore the following events related with the last reception*/
		channelPtr->RxConnection.Substate = CANTP_SUBSTATE_NONE;
    	channelPtr->RxConnection.EventFlags |= CANTP_CHANNEL_EVENT_SF_RECEIVED;
		#if (CANTP_GENERIC_CONNECTION_SUPPORT == STD_ON)
		if (channelPtr->RxConnection.MetaDataLength > 0u)
		{
			result = CanTp_SaveRxMetaDataInfo(channelIdx, RxNSduCfgPtr, CanTpRxPduPtr);
		}
		#endif
    }
    else
    {
        /*idle*/
    }

	return result;
}
/*************************************************************************/
/*
 * Brief               Store the received RXNPDU when indicated.
 * ServiceId           N/A
 * Sync/Async          Synchronous
 * Reentrancy          Non Reentrant
 * Param-Name[in]      CanTpRxPduId ID of received NPDU
 *                     CanTpRxPduPtr pointer to data of received NPDU
 *                     RxNSduCfgPtr pointer to configuration structure of
 *                     this SDU matched with this received NPDU
 * Param-Name[out]     N/A
 * Param-Name[in/out]  N/A
 * Return              E_OK the received NPDU is expected
 *                     E_NOT_OK not expected NPDU
 * PreCondition        Module initialized, a NPDU received.
 * CallByAPI           CanTp_Mainfunctioin
 */
/*************************************************************************/
static FUNC(Std_ReturnType, CANTP_CODE)
CanTp_StoreRxNPduEvt(
    PduIdType CanTpRxPduId,
    P2CONST(PduInfoType, AUTOMATIC, CANTP_APPL_CONST) CanTpRxPduPtr,
    P2CONST(CanTp_RxNSduType, AUTOMATIC, CANTP_CONST) RxNSduCfgPtr,
    CanTp_FramePCIType FrameType,
	uint8 channelIdx,
	P2VAR(boolean, AUTOMATIC, CANTP_CONST) FcFlag
    )
{
    P2VAR(CanTp_ConnectionChannelType, AUTOMATIC, CANTP_VAR_POWER_ON_INIT) channelPtr;
    PduIdType sduId;
    Std_ReturnType result = E_NOT_OK;
    PduLengthType frameDl;
    PduLengthType frameDlLimit = 0;

    sduId = RxNSduCfgPtr->RxNSduId;

    SchM_Enter_CanTp(CANTP_INSTANCE_ID, CANTP_EXCLUSIVE_AREA_CHANNEL); /*lock channel*/
    channelPtr = &CanTp_Channels[channelIdx];
    *FcFlag = FALSE;

    switch (FrameType)
    {
        case CANTP_FTYPE_CF:
        {
            /*min-length check*/
            if (CanTpRxPduPtr->SduLength < 1u)
            {
            	return E_NOT_OK;
            }
            /*only accept it when the channel is receiving a large SDU related with this CF,
             * and it is waiting a CF.*/
            if ((CANTP_FUNCTIONAL_RX == RxNSduCfgPtr->RxTaType)
				#if (STD_ON == CANTP_FD)
				||(CANTP_CANFD_FUNCTIONAL == RxNSduCfgPtr->RxTaType)
				#endif
				)
            {
                /*invalid TAType with CF frame, wrong configuration*/
                #if (CANTP_DEV_ERROR_DETECT == STD_ON)
            	Det_ReportRuntimeError(CANTP_MODULE_ID, CANTP_INSTANCE_ID, CANTP_SERVICEID_RXINDICATION, CANTP_E_PARAM_CONFIG);
                #endif
            }
            else if ((sduId == channelPtr->RxConnection.NSduId)
            		&& (CANTP_LARGE_RECEIVING == channelPtr->RxConnection.RootState)
					&& (CANTP_RX_LARGE_V4CF == channelPtr->RxConnection.Substate))
            {
                result = CanTp_StoreRxNPduInfo(CanTpRxPduId, CanTpRxPduPtr, RxNSduCfgPtr, FrameType, channelIdx);
            }
            else
            {
                /*CF not expected*/
            	result = E_NOT_OK;
            }
            break;
        } /*ENDOF case CANTP_FTYPE_CF*/
        case CANTP_FTYPE_FF:
        {
            /*min-length check*/
            if (CanTpRxPduPtr->SduLength < 2u)
            {
            	return E_NOT_OK;
            }
            /*Only accept FF when the channel is IDLE or it is handling SDU receiving*/
        	/*Function addressing mode not support multiple frames*/
        	if((channelPtr->ChannelMode == CANTP_MODE_HALF_DUPLEX)
				&&(channelPtr->TxConnection.RootState != CANTP_IDLE ))
			{
				/*half duplex, if Tx is in processing, the same channel can not
				 * receiving data at the same time*/
				result = E_NOT_OK;
			}
        	else if ((CANTP_FUNCTIONAL_RX == RxNSduCfgPtr->RxTaType)
					#if (STD_ON == CANTP_FD)
        			||(CANTP_CANFD_FUNCTIONAL == RxNSduCfgPtr->RxTaType)
					#endif
					)
            {
                /*invalid TAType with FF frame, wrong configuration*/
                #if (CANTP_DEV_ERROR_DETECT == STD_ON)
        		Det_ReportRuntimeError(CANTP_MODULE_ID, CANTP_INSTANCE_ID, CANTP_SERVICEID_RXINDICATION, CANTP_E_PARAM_CONFIG);
                #endif
            }
            else if ((CANTP_IDLE == channelPtr->RxConnection.RootState)
                || (CANTP_LARGE_RECEIVING == channelPtr->RxConnection.RootState))
            {
                /*check data length of the FF, ignore the frame if invalid length*/
                frameDl = CanTp_RxGetFFDl(CanTpRxPduPtr->SduDataPtr, RxNSduCfgPtr);

				if (CANTP_STANDARD == RxNSduCfgPtr->AddressingFormat)
				{ /*normal addressing mode*/
                	if (CAN20 == RxNSduCfgPtr->CanFrameType)
					{
                		frameDlLimit = CANTP_SF_LEN_MAX_STD;
                	}
					#if (STD_ON == CANTP_FD)
                	else
                	{
                		/*if CanFd need multiple frames, make its frame length as 64 bytes*/
                		frameDlLimit = CANTP_SF_LEN_MAX_CANFD_STD;
                	}
					#endif/*ENDOF #if (STD_ON == CANTP_FD)*/
                }
				#if (CANTP_EXTENDED_ADDRESSING_SUPPORT == STD_ON)
				else if (CANTP_EXTENDED == RxNSduCfgPtr->AddressingFormat)
				{ /*extended addressing mode*/
					if (CAN20 == RxNSduCfgPtr->CanFrameType)
					{
						frameDlLimit = CANTP_SF_LEN_MAX_EX;
					}
					#if (STD_ON == CANTP_FD)
					else
					{
						/*if CanFd need multiple frames, make its frame length as 64 bytes*/
						frameDlLimit = CANTP_SF_LEN_MAX_CANFD_EX;
					}
					#endif/*ENDOF #if (STD_ON == CANTP_FD)*/
				}
				#endif
				#if (CANTP_NORMAL_FIXED_ADDRESSING_SUPPORT == STD_ON)
				else if (CANTP_NORMALFIXED == RxNSduCfgPtr->AddressingFormat)
				{ /*normal fixed addressing mode*/
					if (CAN20 == RxNSduCfgPtr->CanFrameType)
					{
						frameDlLimit = CANTP_SF_LEN_MAX_NF;
					}
					#if (STD_ON == CANTP_FD)
					else
					{
						/*if CanFd need multiple frames, make its frame length as 64 bytes*/
						frameDlLimit = CANTP_SF_LEN_MAX_CANFD_NF;
					}
					#endif/*ENDOF #if (STD_ON == CANTP_FD)*/
				}
				#endif
				#if (CANTP_MIXED_ADDRESSING_SUPPORT == STD_ON)
				else if (CANTP_MIXED == RxNSduCfgPtr->AddressingFormat)
				{ /*mix11 addressing mode*/
					if (CAN20 == RxNSduCfgPtr->CanFrameType)
					{
						frameDlLimit = CANTP_SF_LEN_MAX_MIX11;
					}
					#if (STD_ON == CANTP_FD)
					else
					{
						/*if CanFd need multiple frames, make its frame length as 64 bytes*/
						frameDlLimit = CANTP_SF_LEN_MAX_CANFD_MIX11;
					}
					#endif/*ENDOF #if (STD_ON == CANTP_FD)*/
				}
				#endif
				#if (CANTP_MIXED29_ADDRESSING_SUPPORT == STD_ON)
				else if (CANTP_MIXED29BIT == RxNSduCfgPtr->AddressingFormat)
				{ /*mix29 addressing mode*/
					if (CAN20 == RxNSduCfgPtr->CanFrameType)
					{
						frameDlLimit = CANTP_SF_LEN_MAX_MIX29;
					}
					#if (STD_ON == CANTP_FD)
					else
					{
						/*if CanFd need multiple frames, make its frame length as 64 bytes*/
						frameDlLimit = CANTP_SF_LEN_MAX_CANFD_MIX29;
					}
					#endif/*ENDOF #if (STD_ON == CANTP_FD)*/
				}
				#endif
				else
				{}

				if (frameDl > frameDlLimit)
				{
					/*store event information*/
					result = CanTp_StoreRxNPduInfo(CanTpRxPduId, CanTpRxPduPtr, RxNSduCfgPtr, FrameType, channelIdx);
				} /*END OF data length checking*/
				else
				{
					result = E_NOT_OK;
				}
            }
            else
            {
                /*FF not expected*/
            	result = E_NOT_OK;
            }
            break;
        } /*ENDOF case CANTP_FTYPE_FF*/
        case CANTP_FTYPE_SF:
        {
            /*min-length check*/
            if (CanTpRxPduPtr->SduLength < 1u)
            {
            	return E_NOT_OK;
            }
            /*Handle FF and SF with the same strategy*/
            /*Only accept SF when the channel is IDLE or it is handling SDU receiving*/
          	if((channelPtr->ChannelMode == CANTP_MODE_HALF_DUPLEX)
				&&(channelPtr->TxConnection.RootState != CANTP_IDLE ))
			{
				/*half duplex, if Tx is in processing, the same channel can not
				 * receiving data at the same time*/
				result = E_NOT_OK;
			}
			else if((CANTP_IDLE == channelPtr->RxConnection.RootState)
					|| (CANTP_LARGE_RECEIVING == channelPtr->RxConnection.RootState))
            {
                /*check data length of the SF, ignore the frame if invalid length*/
                frameDl = CanTp_RxGetSFDl(CanTpRxPduPtr->SduDataPtr, RxNSduCfgPtr);

                if (((8u != CanTpRxPduPtr->SduLength) && (RxNSduCfgPtr->RxPaddingActivation == CANTP_PADDING_ON))
                    || (CanTpRxPduPtr->SduLength <= frameDl))
                {
                	 return E_NOT_OK;
                }

                if (CANTP_STANDARD == RxNSduCfgPtr->AddressingFormat)
                { /*normal addressing mode*/
                	frameDlLimit = CANTP_SF_LEN_MAX_STD;
                }
                #if (CANTP_EXTENDED_ADDRESSING_SUPPORT == STD_ON)
                else if (CANTP_EXTENDED == RxNSduCfgPtr->AddressingFormat)
                { /*extended addressing mode*/
                    frameDlLimit = CANTP_SF_LEN_MAX_EX;
                }
                #endif
				#if (CANTP_NORMAL_FIXED_ADDRESSING_SUPPORT == STD_ON)
				else if (CANTP_NORMALFIXED == RxNSduCfgPtr->AddressingFormat)
				{ /*normal fixed addressing mode*/
					frameDlLimit = CANTP_SF_LEN_MAX_NF;
				}
				#endif
				#if (CANTP_MIXED_ADDRESSING_SUPPORT == STD_ON)
				else if (CANTP_MIXED == RxNSduCfgPtr->AddressingFormat)
				{ /*mix11 addressing mode*/
					frameDlLimit = CANTP_SF_LEN_MAX_MIX11;
				}
				#endif
				#if (CANTP_MIXED29_ADDRESSING_SUPPORT == STD_ON)
				else if (CANTP_MIXED29BIT == RxNSduCfgPtr->AddressingFormat)
				{ /*mix29 addressing mode*/
					frameDlLimit = CANTP_SF_LEN_MAX_MIX29;
				}
				#endif
				else
				{}

                /*frameDl valid*/
				if (frameDl != 0x0u)
				{
					if (CAN20 == RxNSduCfgPtr->CanFrameType)
					{
						/*Can2.0*/
						if (frameDl <= frameDlLimit)
						{
							/*store event information*/
							result = CanTp_StoreRxNPduInfo(CanTpRxPduId, CanTpRxPduPtr, RxNSduCfgPtr, FrameType, channelIdx);
						}
						else
						{
							result = E_NOT_OK;
						}
					}
					#if (STD_ON == CANTP_FD)
					else
					{
						/*CanFd*/
						if ((frameDl <= frameDlLimit)
							||(frameDl == CANTP_SF_LEN_12_CANFD_STD)
							||(frameDl == CANTP_SF_LEN_16_CANFD_STD)
							||(frameDl == CANTP_SF_LEN_20_CANFD_STD)
							||(frameDl == CANTP_SF_LEN_24_CANFD_STD)
							||(frameDl == CANTP_SF_LEN_32_CANFD_STD)
							||(frameDl == CANTP_SF_LEN_48_CANFD_STD)
							||(frameDl == CANTP_SF_LEN_64_CANFD_STD))
						{
							/*store event information*/
							result = CanTp_StoreRxNPduInfo(CanTpRxPduId, CanTpRxPduPtr, RxNSduCfgPtr, FrameType, channelIdx);
						}
						else
						{
							result = E_NOT_OK;
						}
					}/*end of Can frame type check*/
					#endif /*ENDOF #if (STD_ON == CANTP_FD)*/
				}/*end of valid check*/
            }
			else
			{
			    /*idle*/
			}
            break;
        } /*ENDOF case CANTP_FTYPE_SF*/
        default:
            *FcFlag = TRUE;
            /*this will never happen*/
            break;
    } /*END OF switch (frameType) */

    SchM_Exit_CanTp(CANTP_INSTANCE_ID, CANTP_EXCLUSIVE_AREA_CHANNEL); /*unlock channel*/

    return result;
}
/*************************************************************************/
/*
 * Brief               This function is called by the CanTp_RxIndication after a successful
 *                     reception of a RX CAN L-PDU, put the PDU into pool.
 * ServiceId
 * Sync/Async          Synchronous
 * Reentrancy          Reentrant
 * Param-Name[in]      CanTpRxPduId the received N-PDU ID
 *                     CanTpRxPduPtr indicator of structure with received
 *                                   L-SDU(payload) and data length
 * Param-Name[out]     N/A
 * Param-Name[in/out]  N/A
 * Return              N/A
 * PreCondition        CanTp initialized
 * CallByAPI           CanTp_RxIndication
 */
/*************************************************************************/
static FUNC(void, CANTP_CODE)
CanTp_FillRxPdu(
    PduIdType CanTpRxPduId,
    P2CONST(PduInfoType, AUTOMATIC, CANTP_APPL_CONST) CanTpRxPduPtr)
{
    P2CONST(CanTp_RxNSduType, AUTOMATIC, CANTP_CONST) rxNSduCfgPtr;
    P2CONST(CanTp_TxNSduType, AUTOMATIC, CANTP_CONST) txNSduCfgPtr;
    CanTp_FramePCIType sduFrameType;
    uint8 chnIdx;
    boolean fc = TRUE;

    /*first try to check if the received NPDU whether is CF SF or FF*/
	rxNSduCfgPtr = CanTp_GetRxSduCfgByNpdu(CanTpRxPduId, CanTpRxPduPtr, &sduFrameType, &chnIdx);


	/********************************************/
	if (NULL_PTR != rxNSduCfgPtr)
	{
		(void)CanTp_StoreRxNPduEvt(
			CanTpRxPduId,
			CanTpRxPduPtr,
			rxNSduCfgPtr,
			sduFrameType,
			chnIdx,
			&fc);
	}

	if (TRUE == fc)
	{
		/*then check whether it is FC, if FC received that means this is sender*/
		txNSduCfgPtr = CanTp_GetTxSduCfgByFCNpdu(CanTpRxPduId, CanTpRxPduPtr, &chnIdx);
		if (NULL_PTR != txNSduCfgPtr)
		{
			/*A FC received*/
			(void)CanTp_StoreRxFCNPduEvt(
				CanTpRxPduPtr,
				txNSduCfgPtr,
				chnIdx);
		}
	}
}

/*************************************************************************/
/*
 * Brief               Handle Confirm event occurred to the specific channel.
 * ServiceId           N/A
 * Sync/Async          Synchronous
 * Reentrancy          Non Reentrant
 * Param-Name[in]      ChannelIdx index of channel
 * Param-Name[out]     N/A
 * Param-Name[in/out]  N/A
 * Return              N/A.
 * PreCondition        Module initialized.
 * CallByAPI           CanTp_MainFuncation
 */
/*************************************************************************/
static FUNC(void, CANTP_CODE)
CanTp_DispatchCfmEvent(uint8 ChannelIdx)
{
    P2VAR(CanTp_ConnectionChannelType, AUTOMATIC, CANTP_VAR_POWER_ON_INIT) channelPtr;

    channelPtr = &CanTp_Channels[ChannelIdx];

    if ((channelPtr->TxConnection.EventFlags & CANTP_CHANNEL_EVENT_TX_CONFIRMED) != 0u)
    {
        if ((CANTP_TX_SF_V4SF_CFM == channelPtr->TxConnection.Substate)
            || (CANTP_TX_LARGE_V4DATA_CFM == channelPtr->TxConnection.Substate))
        {
            /*A data frame transmit confirmed*/
            CanTp_TxHandleTransmitCfm(ChannelIdx);
        }
        else
        {
            channelPtr->TxConnection.EventFlags =
            		channelPtr->TxConnection.EventFlags & ((uint8)~CANTP_CHANNEL_EVENT_TX_CONFIRMED);
        }
    }

    if ((channelPtr->RxConnection.EventFlags & CANTP_CHANNEL_EVENT_TXFC_CONFIRMED) != 0u)
    {
        if ((CANTP_RX_LARGE_V4FCCTS_CFM == channelPtr->RxConnection.Substate)
            || (CANTP_RX_LARGE_V4FCWT_CFM == channelPtr->RxConnection.Substate))
        {
            /*A data frame transmit confirmed*/
            CanTp_RxHandleFCCfm(ChannelIdx);
        }
        else
        {
            channelPtr->RxConnection.EventFlags =
            		channelPtr->RxConnection.EventFlags & ((uint8)~CANTP_CHANNEL_EVENT_TXFC_CONFIRMED);
        }
    }
}

#define CANTP_STOP_SEC_CODE
#include "Cantp_MemMap.h"
/*=======[E N D   O F   F I L E]==============================================*/
